iT邦幫忙

2022 iThome 鐵人賽

DAY 2
0
AI & Data

文理組人都能上手的入門 NLP(自然語言處理)系列 第 2

[Day 2] NLP好朋友:Python的打開方式—基本語法及資料型態介紹

  • 分享至 

  • xImage
  •  

自然語言處理就是讓機器學會像人一樣理解並處理語言。

  昨天簡單介紹了我所理解的自然語言處理,今天就要開始進入教學文的部分。我們可以把整個NLP的過程看成是在煮菜。我們用來跟電腦溝通的工具-程式語言就是廚具;要拿來用的資料就是食材;不同的訓練方法則是不同的調理方式;最後訓練完成的模型就是煮出來的菜。
  俗話說的好,「工欲善其事,必先利其器」,今天我們就開始認識廚具的使用方法。這個系列的文章選擇python這個牌子來當廚具。然後為了免去一些安裝東西的麻煩,也讓大家可以觀望看看再決定要不要安裝python(畢竟R也是可以拿來做),大家可以參考這篇文章在自己的google雲端上面設定colab。

  說到程式語言,很多沒有接觸過的人可能都會覺得它們像外星語言一樣讓人摸不著頭緒,但其實就跟我們在使用的語言一樣有規則可以探尋,甚至可以說是比一般語言更簡單。因為電腦其實比大家想得都要笨,一定是一個口令一個動作,沒有什麼例外。下面就讓我從python裡面的物件開始介紹。

變數

  在這邊大家可以想像自己是公司裡面擔任比較高職位的人,當有新員工加入的時候,我們會把他們介紹給舊員工,然後安排工作的時候就會叫舊員工帶著新員工做事情。在這裡面python就是有經驗的舊員工,變數則是新員工。所謂的宣告變數就是在把新員工介紹給舊員工認識。我們要先告訴python新員工的名字是什麼,才能進一步指使他要帶著誰做什麼事情。宣告變數的方法是使用=

salary = 168

  打出這行程式碼之後按下儲存格左邊的執行就是在告訴python有一個叫做salary的新員工:168。現在可能有些比較細心謹慎的人就想問我們要怎麼確定python確實認識這個新員工了。前面也提到python就是一個口令一個動作,既然我們有介紹新員工給他的方式,當然也有叫員工出來的方式,那就是print()`。

print(salary)
# 輸出
168

在這間公司裡面,當我們要使喚python幫我們做事的時候就需要用功能指令,使用方式就是像上面那樣先寫出要它做的事,再把指定要做這件事的員工放到括號裡面。

一個公司裡面通常都會有不同部門,員工的特色跟能力也不一樣,所以下面要跟大家介紹這個公司裡面有哪些部門(資料型態)。

數值(numbers)

  就是大家認識的數字們,把他們介紹給python的時候只要像上面那樣打出數字就行。基本上所有你想像得到的運算都可以叫python做。

#加法
168+168
#減法
168-168
#乘法
168*168
#除法
168/168
#次方
168**2

  如果你像我這樣打在colab上面之後執行,應該會發現出來的只有168的平方而已,因為這些運算通常是以一個儲存格為單位,沒有特地把它歸檔的話就只有最後一個指令會留下痕跡(因為最近發生的事情比較容易記住嘛)。所以這個地方有兩個方式,如果你只是單純想叫python像計算機一樣幫你算數,那運用print()就可以了。

print(168+168)
print(168-168)
print(168*168)
print(168/168)
print(168**2)
# 輸出
336
0
28224
1.0
28224

  如果你計算出來的數字後續還會使用到,那就幫他取個名字介紹給python再召喚它出來。

addition = 168+168
minus = 168-168
time = 168*168
divide = 168/168
power = 168**2
print(addition, minus, time, divide, power)
# 輸出
336 0 28224 1.0 28224

字串(strings)

顧名思義就是一串字,在公司裡面標示他們身分的是''""。(兩個都可以,看大家喜好)

message = 'Hello world.'
print(message)
# 輸出
Hello world.

  這樣就完成學程式的人一定會學到的一句話啦~看到這裡不知道有沒有人好奇如果把數字放進字串裡面會發生什麼事?就算你不好奇我也還是要講,因為這很重要。很多資料處理的bug就是出現在我們沒有搞清楚一個變數到底是數值還是字串的時候。

number = 168
string = "168"
print(number)
print(string)
# 輸出
168
168

  是不是覺得看不出差別啊?看著一對同卵雙胞胎員工的臉,我們當然不太能感受到差異。但是當你叫會計師哥哥跟工程師弟弟都去做會計工作的時候,就能感受到差別了。

print(number-number)
print(string-string)
0
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-3855715bf4cb> in <module>
      1 print(number-number)
----> 2 print(string-string)

TypeError: unsupported operand type(s) for -: 'str' and 'str'

  我們可以看到第一行的程式碼被順利執行了,但第二行的結果好像沒有出來。這裡跟大家說,看到error code的時候千萬不要慌張。先找到箭頭指的地方,因為那是出錯的部分。再來就是最後一行字,它會告訴你到底是哪裡出了問題。從最後一行字能觀察到我們遇到的是TypeError,因為我們把字串str拿來做-這個只能用在數值int的指令。這樣大家應該就可以感受到數值跟字串的差異,當一個變數是字串的時候,即便裡面放的是數字,對python來說它就只是文字而已,工程師是不能做會計工作的。

  現在問題就來了,當我們公司越做越大,員工越來越多的時候,要記住每個人的部門也就越難,程式寫著寫著一定會遇到搞混的情況。在一般公司想知道其他人的所屬部門可以看他們的識別證,所以在python裡面當然也可以把變數的識別證叫出來看一下他所屬的部門是什麼,只要使用type()就行。

print(type(number))
print(type(string))

  這個地方python的運作方式跟數學的四則運算一樣,當有很多括號出現的時候,一定是先從最裡面的括號開始做起。所以我們先叫他找出number這個員工的識別證再用print()把它印出來,就可以得到下面的結果。

# 輸出
<class 'int'>
<class 'str'>

  它告訴我們number的所屬部門是int(integer的縮寫),string的所屬部門則是str(string的縮寫),所以number是數值、string是字串。type()是用來確認變數資料型態的指令,所以針對下面介紹的資料型態也都有效果。

  有時候公司要執行大型企畫的時候會成立專案小組。這個小組裡面會集合各種各樣來自不同部門的人去分工。接下來要介紹的三種資料型態就像是這個專案小組的名單一樣。

串列(list)

  串列是一個很重視順序但是具有彈性的組員名單,裡面可以放字串跟數字,也可以同時存放兩者,你甚至可以再放一個串列進去也沒問題。宣告方式是把變數用,隔開並用[]括起來。

fruit = ["apple", "orange", "banana"]
price = [20, 18, 30]
fruit_price = ["apple", 20, "orange", 18, "banana", 30]
print(fruit)
print(price)
print(fruit_price)
# 輸出
['apple', 'orange', 'banana']
[20, 18, 30]
['apple', 20, 'orange', 18, 'banana', 30]

  這邊不知道大家有沒有注意到一個細節。剛剛我們單純把一個字串印出來的時候是不會出現''""的,但是在串列裡面的時候卻會清楚地顯示出來。由此可見,如果我們的資料是存在串列裡面,直接把串列印出來就可以看到裡面每一個物件的屬性了。

  如果不想一次看到串列裡面的所有資料,只想叫出特定順序的東西的話可以用下面這個方式。串列名稱加上被[]框起來的,你想要看到的索引值。(特別注意:python的數字排序從0開始,所以第一個物件的索引值(index)是0,依此類推)

print(fruit[1]) #印出fruit這個串列裡的第2個物件
# 輸出
'orange'

因為串列是有彈性的名單,所以我們可以增刪或修改裡面的資料。

# 修改第一筆資料
fruit[0] = "pineapple"
print(fruit)

如果單純只是想修改特定的某筆資料,那就用=把它替代成新的資料就好

# 輸出
['pineapple', 'orange', 'banana']
# 加入新的資料
fruit.append("strawberry")
print(fruit)

# 把新資料加在特定位置
fruit.insert(0, "apple")
print(fruit)
# 輸出
['pineapple', 'orange', 'banana', 'strawberry']
['apple', 'pineapple', 'orange', 'banana', 'strawberry']

  因為不同部門的員工會的技能都不同,所以不同資料型態也會有自己內建能使用的指令。當我們要使用這些內建指令的時候,只要在變數後面加上.之後打出指令就可以了。
   使用insert()可以直接在原本的串列最後加入新資料,但如果想要把新資料插進特定的位置,就要使用insert()insert()跟我們前面看到的指令都不同,括號裡面需要放進兩個東西,第一個是你希望新資料插進去之後所在的位置(就是索引值),第二個才是你要插進去的新資料。

# 刪掉最後一個資料
fruit.pop()
print(fruit)
# 刪掉特定位置的資料
fruit.pop(1)
print(fruit)
# 刪掉特定資料
fruit.remove("banana")
print(fruit)
['apple', 'pineapple', 'orange', 'banana']
['apple', 'orange', 'banana']
['apple', 'orange']

  使用pop()這個指令的時候,如果你想刪掉最後一筆資料,括號裡面可以不填東西,因為他的預設值就是最後一筆資料;如果是其他位置的資料就在裡面指定它的索引值;如果只知道要刪的資料內容,不知道位置的話,可以使用remove()填入資料內容。

元組(tuple)

  如果說串列是計畫執行初期的組員名單,所以可以改來改去的話,那元祖就是最終最終決定好的組員名單,不能再修改了。這適用於你不希望串列裡面的資料有被修改風險的時候。宣告方式是把資料用()括起來。

decided_fruit = ("apple", "pineapple", "orange", "banana", "strawberry")
print(decided_fruit)
('apple', 'pineapple', 'orange', 'banana', 'strawberry')

基本上元組跟跟串列的不同就只在括號樣式跟能不能修改而已,其他索引的方式都跟串列一樣,我們還是可以只請它告訴我們特定索引值的資料是什麼,只要不修改裡面的資料就好。

print(decided_fruit[1])
decided_fruit[1] = "pear"
# 輸出
pineapple
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-10-6363e9e85485> in <module>
      1 print(decided_fruit[1])
----> 2 decided_fruit[1] = "pear"

TypeError: 'tuple' object does not support item assignment

如果我們試圖修改元組裡面的資料,python就會祭出error message來警告我們不能這樣。

字典(dict)

終於來到今天最後一個資料型態-字典了。它其實就像專案企劃的分工名單一樣,可以拿來記錄每個人負責什麼樣的工作,或是每個工作的負責人是誰。字典這個取名真的比串列跟元組直覺太多了。一般來說如果是單語字典裡面就是會有單字跟它的意思,如果是雙語字典就會兩個語言裡面最相似、可以拿來對照的單字出現。在python裡面這兩個元素叫做keyvalue,如果今天我們用一本英漢字典查詢某個英文單字的中文,那這個英文單字就是key,對應的中文單字則是value。下面繼續用水果跟他們的價格來示範。

fruit_price = {'apple':20, 'orange':18, 'banana':30}
print(fruit_price)
# 輸出
{'apple': 20, 'orange': 18, 'banana': 30}

當我們想要知道蘋果價錢的時候,就呼喚蘋果來確認它的價錢。

fruit_price["apple"]
# 輸出
20

關於字典這個資料型態,我們需要特別注意的是,因為它著重在keyvalue之間的對應,所以順序不是那麼重要的東西,它不會有索引值。每次叫字典出來的時候,裡面的順序也可能會不同。如果想要增加或是修改東西的話只要用宣告的方式就行。

# 修改資料
fruit_price["orange"] = 15
print(fruit_price)
# 增加資料
fruit_price["strawberry"] = 50
print(fruit_price)
# 輸出
{'apple': 20, 'orange': 15, 'banana': 30}
{'apple': 20, 'orange': 15, 'banana': 30, 'strawberry': 50}

如果想刪掉東西,一樣用可以用pop()達成。

fruit_price.pop('strawberry')
print(fruit_price)
# 輸出
{'apple': 20, 'orange': 15, 'banana': 30}

  好啦今天就到這邊,最後附上這幾個資料型態的比較。

宣告方式 特色
數值(numbers) X 可以做運算
字串(strings) " " or ' ' 存放文字
串列(list) [ ] 可以同時存放數值、字串跟串列/有順序性/可以修改
元組(tuple) ( ) 可以同時存放數值、字串跟串列/有順序性/不能修改
字典(dict) {key:value} 一對一的關係/沒有順序性

  如果覺得這篇文章對你有幫助或是喜歡這篇文章的話可以幫我點個愛心。發現有bug或是有問題想問的話也歡迎下面留言~明天見


上一篇
[Day 1] 我眼中的自然語言處理
下一篇
[Day 3] NLP好朋友:Python的打開方式–字串處理
系列文
文理組人都能上手的入門 NLP(自然語言處理)31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言